﻿// HXMultiThreadPrintABC.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <thread>
#include <mutex>
#include <memory>
#include <Windows.h>
//
//typedef struct MyStruct
//{
//    std::shared_ptr<std::mutex> m_pmutexWait;
//    std::shared_ptr<std::mutex> m_pmutexLock;
//    char                        m_cShow;
//    bool                        m_bFirst;
//    MyStruct() : m_cShow('\0'), m_bFirst(false), m_pmutexWait(nullptr), m_pmutexLock(nullptr){}
//}*LPMyStruct;
//
//void __stdcall FuncPrint(LPMyStruct pParam)
//{
//    if (nullptr == pParam)
//    {
//        return;
//    }
//    while (true)
//    {
//        pParam->m_pmutexLock->lock();
//        pParam->m_pmutexWait->lock();
//        //std::lock_guard(pParam->m_pmutexLock);
//        std::cout << pParam->m_cShow << std::endl;
//        pParam->m_pmutexLock->unlock();
//    }
//}

typedef struct MyStruct
{
    HANDLE                      m_hWait;
    HANDLE                      m_hNextWait;
    char                        m_cShow;
    volatile bool               m_bClose;
    MyStruct()
        : m_cShow('\0'),
        m_bClose(false),
        m_hWait(INVALID_HANDLE_VALUE),
        m_hNextWait(INVALID_HANDLE_VALUE) {}
}*LPMyStruct;

unsigned __stdcall FuncPrint( LPVOID pVoid)
{
    if (nullptr == pVoid)
    {
        return -1;
    }
    while (true)
    {
        LPMyStruct pParam = (LPMyStruct)pVoid;
        if (INVALID_HANDLE_VALUE == pParam->m_hWait 
            || INVALID_HANDLE_VALUE == pParam->m_hNextWait)
        {
            return -1;
        }
        ::WaitForSingleObject(pParam->m_hWait, -1);
        std::cout << pParam->m_cShow << std::endl;
        ::SetEvent(pParam->m_hNextWait);
    }
    return 0;
}

int main()
{
    //std::shared_ptr<std::mutex> pmutexBWaitA = std::make_shared<std::mutex>();
    //std::shared_ptr<std::mutex> pmutexAWaitC = std::make_shared<std::mutex>();
    //std::shared_ptr<std::mutex> pmutexCWaitB = std::make_shared<std::mutex>();
    //MyStruct dataA;
    //dataA.m_cShow = 'A';
    //dataA.m_pmutexWait = pmutexAWaitC;
    //MyStruct dataB;
    //dataB.m_cShow = 'B';
    //dataB.m_pmutexWait = pmutexBWaitA;
    //MyStruct dataC;
    //dataC.m_cShow = 'C';
    //dataB.m_pmutexWait = pmutexCWaitB;

    HANDLE hWaitAWaitC = ::CreateEvent(NULL, false, false, NULL);
    HANDLE hWaitBWaitA = ::CreateEvent(NULL, false, false, NULL);
    HANDLE hWaitCWaitB = ::CreateEvent(NULL, false, false, NULL);
    MyStruct dataA;
    dataA.m_cShow = 'A';
    dataA.m_hWait = hWaitAWaitC;
    dataA.m_hNextWait = hWaitBWaitA;
    MyStruct dataB;
    dataB.m_cShow = 'B';
    dataB.m_hWait = hWaitBWaitA;
    dataB.m_hNextWait = hWaitCWaitB;
    MyStruct dataC;
    dataC.m_cShow = 'C';
    dataC.m_hWait = hWaitCWaitB;
    dataC.m_hNextWait = hWaitAWaitC;

    unsigned threadIDA, threadIDB, threadIDC;
    HANDLE hA = (HANDLE)_beginthreadex(NULL, 0, &FuncPrint, (LPVOID)(&dataA), 0, &threadIDA);
    HANDLE hB = (HANDLE)_beginthreadex(NULL, 0, &FuncPrint, (LPVOID)(&dataB), 0, &threadIDB);
    HANDLE hC = (HANDLE)_beginthreadex(NULL, 0, &FuncPrint, (LPVOID)(&dataC), 0, &threadIDC);

    if (INVALID_HANDLE_VALUE == hA
        || INVALID_HANDLE_VALUE == hB
        || INVALID_HANDLE_VALUE == hC)
    {
        _ASSERT(0);
    }
    SetEvent(hWaitAWaitC);

    WaitForSingleObject(hA, INFINITE);
    WaitForSingleObject(hB, INFINITE);
    WaitForSingleObject(hC, INFINITE);
    //std::thread threadA(FuncPrint, dataA);
    //std::thread threadB(FuncPrint, dataB);
    //std::thread threadC(FuncPrint, dataC);

    //threadA.join();
    //threadB.join();
    //threadC.join();


    system("pause");
    std::cout << "Hello World!\n";
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件，或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来，若要再次打开此项目，请转到“文件”>“打开”>“项目”并选择 .sln 文件
